import re

from matplotlib.pyplot import broken_barh
from ICF.Trainer import Trainer
from tqdm import tqdm
from typing import Dict, List


class Recommender:
    def __init__(self, hyper_params):
        self.hyper_params = hyper_params

        self.trainer = Trainer(hyper_params)
        self.user_cnt = self.trainer.file_loader.reader_cnt
        self.item_cnt = self.trainer.file_loader.book_cnt

        self.W: Dict[int, Dict[int, float]] = self.trainer.W
        self.user_book_list: Dict[int, List[int]
                                  ] = self.trainer.interaction_list

    def recommend(self, max_cnt=500) -> Dict[int, List[int]]:
        print('ICF: Start Item-based CF recommendation...')
        result: Dict[int, List[int]] = {}

        for user in tqdm(range(self.user_cnt)):
            result[user] = []

            item_score: Dict[int, float] = {}

            for item in self.user_book_list[user]:
                for k, v in self.W[item].items():
                    if k not in item_score:
                        item_score[k] = 0.0

                    item_score[k] += v

            if len(item_score) == 0:
                continue

            item_score_list = sorted(
                item_score.items(), key=lambda x: x[1], reverse=True)

            cnt = 0
            for book, _ in item_score_list:
                result[user].append(book)
                cnt += 1

                if cnt >= 500:
                    break

        print('ICF: Finished Item-based CF recommendation.')
        return result


if __name__ == '__main__':
    hyper_params = {
        'dataset_path': '../datasets/lib.txt'
    }

    recommender = Recommender(hyper_params)
    result = recommender.recommend(max_cnt=500)

    print(result)
